package fr.labri.buganalyzer.datamining;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import fr.labri.buganalyzer.model.Change;
import fr.labri.buganalyzer.model.Issue;
import fr.labri.buganalyzer.writers.H2Adapter;

public final class DataExtractor {

	public static final String DB_FILE = "resources/testData/ProductionIssuesDB_eclipse_e4";
	public static final String OUTPUT_FOLDER = "resources/testData/";

	private List<Project> projects;
	private Session session;

	private DataExtractor(String dbFile, String outputFolder) {
		projects = new ArrayList<Project>();
		H2Adapter adapter = new H2Adapter(dbFile);
		this.session = adapter.getSession();
	}

	public void save(Path path, StringBuilder data) throws IOException {
		Path file = Files.createFile(path);
		try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8, StandardOpenOption.WRITE)) {
			writer.write(data.toString());
		}
	}

	private void loadProjects(String file) throws IOException {
		List<String> lines = Files.readAllLines(Paths.get(file), StandardCharsets.UTF_8);
		for (String s : lines) {
			String[] res = s.split(",");
			this.projects.add(new Project(res[0], res[1], res[2]));
		}
	}

	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws IOException {
		DataExtractor extractor = new DataExtractor(DB_FILE, OUTPUT_FOLDER);
		extractor.loadProjects(args[0]);
		Session session = extractor.getSession();

		for (Project p : extractor.projects) {
			List<Map<String, String>> result = new ArrayList<Map<String, String>>();
			Iterator<?> issueChangeMaps = session.createCriteria(Issue.class)
											.createAlias("changes", "change")
											.add(Restrictions.like("component", p.getComponent()))
											.add(Restrictions.like("product", p.getProduct()))
											.add(Restrictions.like("change.newValue", "RESOLVED"))
											.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP)
											.list().iterator();
			
			while (issueChangeMaps.hasNext()) {
				Map<String, Object> map = (Map<String, Object>) issueChangeMaps.next();
				Issue issue = (Issue) map.get("this");
				Change change = (Change) map.get("change");
				Map<String, String> mapp = new HashMap<String, String>();
				mapp.put("issueNumber", issue.getNumber() + "");
				mapp.put("creationDate", issue.getSubmittedOn().toString());
				mapp.put("closeDate", change.getChangedOn().toString());
				result.add(mapp);
			}
			extractor.writeJson(p, result);
		}

	}


	private void writeJson(Project p, List<Map<String, String>> issueInfo) throws IOException {
		Map<String, Object> projectData = new HashMap<String, Object>();
		List<Map<String, String>> issues = new ArrayList<Map<String, String>>();

		projectData.put("URL", p.getVcsUrl());
		projectData.put("product", p.getProduct());
		projectData.put("component", p.getComponent());
		projectData.put("numberOfIssues", issueInfo.size());
		
		for (Map<String, String> entry : issueInfo) {
			Map<String, String> issueData = new HashMap<String, String>();
			issueData.put("issueNumber", entry.get("issueNumber"));
			issueData.put("creationDate", entry.get("creationDate"));
			issueData.put("closeDate", entry.get("closeDate"));
			issues.add(issueData);
		}
		projectData.put("issues" , issues);
		
		String filename = (p.getProduct() + "_" + p.getComponent()).replaceAll(" ", "");
		ObjectMapper mapper = new ObjectMapper();
		mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
		mapper.writeValue(new File("resources/testData/" + filename + ".json"), projectData);
	}

	public Session getSession() {
		return session;
	}
	
	class Project {

		private String product;
		private String component;
		private String vcsUrl;

		public Project(String product, String component, String vcsUrl) {
			super();
			this.product = product;
			this.component = component;
			this.vcsUrl = vcsUrl;
		}

		public String getProduct() {
			return product;
		}

		public void setProduct(String product) {
			this.product = product;
		}

		public String getComponent() {
			return component;
		}

		public void setComponent(String component) {
			this.component = component;
		}

		public String getVcsUrl() {
			return vcsUrl;
		}

		public void setVcsUrl(String vcsUrl) {
			this.vcsUrl = vcsUrl;
		}

	}



}
